<template>
    <div v-if="formConfigComputed.length > 0">
        <el-form
            ref="submitFormRef"
            :inline="inline"
            :class="{ secForm: true, sqForm: formStatus }"
            :rules="formRule"
            :model="formData"
            :label-position="labelPson"
            :label-width="labelwth"
        >
            <div
                :class="[
                    grid && grid !== -1 ? 'grid_list grid_list_' + grid : '',
                    grid === -1 ? 'grid_list grid_list_auto' : '',
                ]"
                :style="getStype1()"
            >
                <div v-for="(item, i) in formConfigComputed" :key="i" :style="getStyle(item)">
                    <!-- 不包含formItem的插槽 -->
                    <template v-if="item.type === 'customAll' && item.slot">
                        <slot :name="item.slot" :item="item"></slot>
                    </template>
                    <!-- 包含formItem的插槽 -->
                    <el-form-item
                        v-if="item.type === 'customInput'"
                        class="secForm__item customInput"
                        :label="item.label || ''"
                        :prop="item.modelName || ''"
                        :required="item.required"
                    >
                        <slot :name="item.slot" :item="item"></slot>
                    </el-form-item>

                    <el-form-item
                        v-if="item.type === 'text'"
                        class="secForm__item"
                        :label="item.label || ''"
                        :prop="item.modelName || ''"
                    >
                        <slot v-if="item.slot" :name="item.slot" :item="item">
                            {{
                                typeof item.render === 'function'
                                    ? item.render(formData[item.modelName])
                                    : formData[item.modelName]
                            }}
                        </slot>

                        <template v-else>
                            <div class="content">
                                {{
                                    typeof item.render === 'function'
                                        ? item.render(formData[item.modelName])
                                        : formData[item.modelName]
                                }}
                            </div>
                        </template>
                    </el-form-item>

                    <el-form-item
                        v-if="item.type === 'input' || item.type === 'password'"
                        class="secForm__item"
                        :label="item.label"
                        :prop="item.modelName"
                    >
                        <el-input
                            v-model.trim="formData[item.modelName]"
                            :placeholder="
                                item.disabled && item.placeholder
                                    ? item.placeholder
                                    : item.disabled
                                    ? ''
                                    : item.placeholder
                                    ? item.placeholder
                                    : '请输入' + item.label
                            "
                            :clearable="true"
                            :disabled="item.disabled ? true : false"
                            :readonly="item.readonly ? true : false"
                            :show-password="item.type === 'password'"
                            :maxlength="item.maxLength || 100"
                            :show-word-limit="item.showWordLimit || false"
                            :class="[item.className]"
                            @blur="
                                (event) => {
                                    item.blurFn && item.blurFn(event.target.value)
                                }
                            "
                            @keyup.enter.native="
                                (event) => {
                                    item.enterFn && item.enterFn(event.target.value)
                                }
                            "
                            @clear="
                                () => {
                                    item.clearFn && item.clearFn()
                                }
                            "
                        />
                        <el-tooltip
                            v-if="item.tip"
                            effect="dark"
                            :content="item.tip"
                            placement="top-start"
                        >
                            <i class="el-icon-question m-l-10 f-22 c-888"></i>
                        </el-tooltip>
                    </el-form-item>

                    <!-- 只读展示 -->
                    <el-form-item
                        v-if="item.type === 'readOnly'"
                        class="secForm__item"
                        :label="item.label"
                        :prop="item.modelName"
                    >
                        <div>{{ formData[item.modelName] }}</div>
                    </el-form-item>

                    <el-form-item
                        v-if="item.type === 'inputNumber'"
                        class="secForm__item"
                        :label="item.label"
                        :prop="item.modelName"
                    >
                        <kl-input
                            v-model="formData[item.modelName]"
                            :min="item.min ? item.min : 0"
                            :max="item.max || item.max === 0 ? item.max : 10000000000000"
                            :placeholder="
                                item.disabled
                                    ? ''
                                    : item.placeholder
                                    ? item.placeholder
                                    : '请输入' + item.label
                            "
                            :class="[item.className]"
                            :clearable="item.clearable ? item.clearable : false"
                            class="widthStyle"
                            :disabled="item.disabled ? true : false"
                        ></kl-input>
                    </el-form-item>

                    <el-form-item
                        v-if="item.type === 'textarea'"
                        class="secForm__item"
                        :label="item.label"
                        :prop="item.modelName"
                    >
                        <el-input
                            v-model="formData[item.modelName]"
                            :type="item.type"
                            :placeholder="
                                item.disabled
                                    ? ''
                                    : item.placeholder
                                    ? item.placeholder
                                    : '请输入' + item.label
                            "
                            :disabled="item.disabled ? true : false"
                            :autosize="item.autosize ? item.autosize : true"
                            :maxlength="item.maxLength || 300"
                            :show-word-limit="item.showWordLimit || false"
                            :resize="item.resize"
                            :style="{ width: item.width ? item.width : '' }"
                            :rows="item.rows || 3"
                        />
                    </el-form-item>
                    <el-form-item
                        v-if="item.type === 'select'"
                        class="secForm__item"
                        :label="item.label"
                        :prop="item.modelName"
                    >
                        <el-select
                            :class="[item.className]"
                            :value.sync="formData[item.modelName]"
                            :value-key="item.valueKey || 'code'"
                            :clearable="item.clearable !== undefined ? item.clearable : true"
                            :multiple="item.isMuli ? item.multiple : false"
                            :filterable="item.isFilter ? item.isFilter : false"
                            :allow-create="item.allowCreate ? item.allowCreate : false"
                            :default-first-option="
                                item.defaultFirstOption ? item.defaultFirstOption : false
                            "
                            :remote="item.isRemote ? item.isRemote : false"
                            :remote-method="
                                item.isRemote ? ($event) => handleSelectRemote($event, item) : null
                            "
                            :disabled="item.disabled ? true : false"
                            :loading="item.loading ? item.loading : false"
                            :placeholder="
                                item.disabled
                                    ? ''
                                    : item.placeholder
                                    ? item.placeholder
                                    : `请选择${item.label}`.replace(/(选择)\1+/g, '$1')
                            "
                            :collapse-tags="!!item.isCollapse"
                            @change="($event) => handleSelectChange($event, item)"
                            @clear="() => handleSelectClear(item)"
                            @focus="($event) => handleSelectFocus($event, item)"
                        >
                            <el-option
                                v-for="op in item.options"
                                :key="item.valueKey ? op[item.valueKey] : op.value"
                                :disabled="op.disabled ? op.disabled : false"
                                :label="item.labelKey ? op[item.labelKey] : op.label"
                                :value="
                                    item.valueType === 'object'
                                        ? op
                                        : item.valueKey
                                        ? op[item.valueKey]
                                        : op.value
                                "
                            >
                                <div
                                    :class="
                                        item.widthAuto
                                            ? 'select-option-width-auto'
                                            : 'select-option-width'
                                    "
                                >
                                    <span v-if="item.optionRender">
                                        {{ item.optionRender(op) }}
                                    </span>
                                    <template v-else>
                                        {{ item.labelKey ? op[item.labelKey] : op.label }}
                                    </template>
                                </div>
                            </el-option>
                        </el-select>

                        <el-tooltip
                            v-if="item.tip"
                            effect="dark"
                            :content="item.tip"
                            placement="top-start"
                        >
                            <i class="el-icon-question m-l-10 f-22 c-888"></i>
                        </el-tooltip>
                    </el-form-item>

                    <el-form-item
                        v-if="item.type === 'cascader'"
                        class="secForm__item"
                        :label="item.label"
                        :prop="item.modelName"
                    >
                        <el-cascader
                            v-model="formData[item.modelName]"
                            clearable
                            filterable
                            :options="item.options"
                            :props="item.props"
                            :placeholder="
                                item.disabled
                                    ? ''
                                    : item.placeholder
                                    ? item.placeholder
                                    : '请选择' + item.label
                            "
                            :popper-class="item.class"
                        />
                    </el-form-item>

                    <el-form-item
                        v-if="item.type === 'radioGroup'"
                        class="secForm__item"
                        :label="item.label"
                        :prop="item.modelName"
                        :label-width="item.labelWidth ? item.labelWidth : labelwth"
                    >
                        <el-radio-group
                            v-model="formData[item.modelName]"
                            :disabled="item.disabled"
                        >
                            <template v-if="item.radioButton">
                                <el-radio-button
                                    v-for="(j, index) in item.options"
                                    :key="index"
                                    :label="j.value"
                                    :disabled="j.disabled ? true : false"
                                >
                                    <span v-text="j.label" />
                                </el-radio-button>
                            </template>
                            <template v-else>
                                <el-radio
                                    v-for="(j, index) in item.options"
                                    :key="index"
                                    :label="j.value"
                                    :disabled="j.disabled ? true : false"
                                >
                                    <span v-text="j.label" />
                                </el-radio>
                            </template>
                        </el-radio-group>
                    </el-form-item>
                    <el-form-item
                        v-if="item.type === 'checkbox'"
                        class="secForm__item"
                        :label="item.label"
                        :prop="item.modelName"
                    >
                        <el-checkbox
                            v-model="formData[item.modelName]"
                            :disabled="item.disabled ? true : false"
                        >
                            <span v-text="item.CheckboxText" />
                        </el-checkbox>
                    </el-form-item>
                    <el-form-item
                        v-if="item.type === 'checkboxGroup'"
                        class="secForm__item"
                        :label="item.label"
                        :prop="item.modelName"
                    >
                        <el-checkbox-group
                            v-model="formData[item.modelName]"
                            :min="item.min ? item.min : 0"
                            :max="item.max ? item.max : 100000"
                        >
                            <template v-if="!item.checkboxButton">
                                <el-checkbox
                                    v-for="(j, index) in item.options"
                                    :key="index"
                                    :label="item.valueKey ? j[item.valueKey] : j.value"
                                    :disabled="j.disabled ? true : false"
                                >
                                    <span v-text="item.labelKey ? j[item.labelKey] : j.label" />
                                </el-checkbox>
                            </template>
                            <template v-else>
                                <el-checkbox-button
                                    v-for="(j, index) in item.options"
                                    :key="index"
                                    :label="item.valueKey ? j[item.valueKey] : j.value"
                                    :disabled="j.disabled ? true : false"
                                >
                                    <span v-text="item.labelKey ? j[item.labelKey] : j.label" />
                                </el-checkbox-button>
                            </template>
                        </el-checkbox-group>
                    </el-form-item>
                    <el-form-item
                        v-if="item.type === 'datePicker'"
                        class="secForm__item"
                        :label="item.label"
                        :prop="item.modelName"
                    >
                        <el-date-picker
                            v-model="formData[item.modelName]"
                            :type="item.isNeedTime ? 'datetime' : 'date'"
                            :class="[item.className]"
                            :placeholder="
                                item.disabled
                                    ? ''
                                    : item.placeholder
                                    ? item.placeholder
                                    : '请输入' + item.label
                            "
                            :picker-options="item.pickerOptions ? item.pickerOptions : ''"
                            :default-value="item.defaultValue ? item.defaultValue : ''"
                            :disabled="item.disabled ? true : false"
                            :value-format="
                                item.valueFormat === undefined
                                    ? 'yyyy-MM-dd HH:mm:ss'
                                    : item.valueFormat
                            "
                            :format="
                                item.format === undefined ? 'yyyy-MM-dd HH:mm:ss' : item.format
                            "
                        />
                    </el-form-item>
                    <el-form-item
                        v-if="item.type === 'datetimerange' && item.isArray"
                        class="secForm__item2"
                        :label="item.label"
                        :prop="item.modelName.join('&')"
                    >
                        <el-date-picker
                            v-model="formData[item.modelName.join('&')]"
                            class="item__datePicker"
                            :type="item.isNeedTime ? 'datetimerange' : 'daterange'"
                            :range-separator="item.rangeSeparator ? item.rangeSeparator : '至'"
                            start-placeholder="开始日期"
                            end-placeholder="结束日期"
                            :default-time="['00:00:00', '23:59:59']"
                            :value-format="item.valueType"
                            :format="item.format"
                            :disabled="item.disabled ? true : false"
                        />
                    </el-form-item>
                    <el-form-item
                        v-if="item.type === 'datetimerange' && !item.isArray"
                        class="secForm__item2"
                        :label="item.label"
                        :prop="item.modelName"
                    >
                        <el-date-picker
                            v-model="formData[item.modelName]"
                            class="item__datePicker"
                            :type="item.isNeedTime ? 'datetimerange' : 'daterange'"
                            :range-separator="item.rangeSeparator ? item.rangeSeparator : '至'"
                            start-placeholder="开始日期"
                            end-placeholder="结束日期"
                            :default-time="['00:00:00', '23:59:59']"
                            :value-format="item.valueType"
                            :format="item.format"
                            :disabled="item.disabled ? true : false"
                            @change="
                                (val) => {
                                    item.changeFn && item.changeFn(val)
                                }
                            "
                        />
                    </el-form-item>
                    <!-- 多选 -->
                    <el-form-item
                        v-if="item.type === 'selectAll'"
                        class="secForm__item"
                        :label="item.label"
                        :prop="item.modelName"
                    >
                        <select-all
                            v-model="formData[item.modelName]"
                            :placeholder="
                                item.placeholder ? item.placeholder : '请选择' + item.label
                            "
                            :options="item.options"
                            :valueKey="item.valueKey"
                            :labelKey="item.labelKey"
                            :clearable="true"
                            :multiple="true"
                            :filterable="item.isFilter ? item.isFilter : false"
                            :collapse-tags="item.isCollapse ? item.isCollapse : false"
                        />
                    </el-form-item>
                    <!-- 时间范围 -->
                    <el-form-item
                        v-if="item.type === 'timerange'"
                        class="secForm__item2"
                        :label="item.label"
                        :prop="item.modelName"
                        :key="i"
                    >
                        <el-time-picker
                            v-model="formData[item.modelName]"
                            class="item__timePicker"
                            is-range
                            :range-separator="item.rangeSeparator || '至'"
                            start-placeholder="开始时间"
                            end-placeholder="结束时间"
                            :clearable="!!item.clearable"
                            :value-format="item.valueType || 'HH:mm'"
                            :format="item.format || 'HH:mm'"
                            :picker-options="{ format: item.format || 'HH:mm' }"
                            :disabled="!!item.disabled"
                        />
                    </el-form-item>

                    <!-- 附件上传 -->
                    <el-form-item
                        v-if="item.type === 'upload'"
                        class="secForm__item2"
                        :label="item.label"
                        :prop="item.modelName"
                        :key="i"
                    >
                        <SceneUploader
                            :value.sync="formData[item.modelName]"
                            :readonly="!!item.disabled || !!item.readonly"
                            :max-count="item.maxCount || 10"
                            :max-size="item.maxSize || 50"
                            :is-image-only="item.isImageOnly || false"
                            :is-video-only="item.isVideoOnly || false"
                            @change="
                                (val) => {
                                    item.changeFn && item.changeFn(val)
                                }
                            "
                        >
                            <template slot="head" slot-scope="scope">
                                <div>
                                    <span
                                        v-if="!item.disabled && !item.readonly"
                                        v-html="
                                            item.tips
                                                ? typeof item.tips === 'function'
                                                    ? item.tips()
                                                    : item.tips
                                                : ''
                                        "
                                    ></span>
                                    （{{
                                        Array.isArray(formData[item.modelName])
                                            ? formData[item.modelName].length
                                            : 0
                                    }}/{{ scope.maxCount }}）：
                                </div>
                            </template>
                        </SceneUploader>
                    </el-form-item>
                </div>
            </div>
        </el-form>
    </div>
</template>

<script>
export default {
    name: 'e-form',
    components: {
        sceneUploader: () => import('@/components/async/sceneUploader.vue'),
        SelectAll: () => import('@/components/async/SelectAll.vue'),
        PagingSelectComp: () => import('@/components/async/PagingSelectComp.vue'),
    },
    props: {
        formConfig: {
            type: Array,
            default: function () {
                return []
            },
        },
        labelWidth: {
            type: String,
            default: '115px',
        },
        labelPosition: {
            type: String,
            default: 'right',
        },
        formRule: {
            type: Object,
            default: function () {
                return {}
            },
        },
        formData: {
            type: Object,
            default: function () {
                return {}
            },
        },
        inline: {
            type: Boolean,
            default: false,
        },
        grid: {
            type: Number,
            default: 0,
        },
    },
    data() {
        return {
            formStatus: false,
        }
    },
    computed: {
        labelwth() {
            return this.labelWidth ? this.labelWidth : '100px'
        },
        labelPson() {
            return this.labelPosition ? this.labelPosition : 'right'
        },
        formConfigComputed() {
            return this.formConfig.filter((item) => {
                const { show } = item
                const showType = this.getType(show)
                if (showType === 'boolean') {
                    return show
                } else if (showType === 'function') {
                    return show(item)
                } else if (showType === 'undefined') {
                    return true
                } else {
                    this.$Toast(`${item.label}show 字段类型错误，不支持 ${showType} 类型`)
                    return true
                }
            })
        },
    },
    mounted() {
        this.$emit('forwardFormRef', this.$refs.submitFormRef)
        this.initFormConfig()
    },
    methods: {
        // 设置表单初始值，设置为响应式对象
        async initFormConfig() {
            for (let i = 0; i < this.formConfigComputed.length; i++) {
                const item = this.formConfigComputed[i]
                const { type, clearable, modelName, options, filterable } = item

                // 设置options值
                if (options) {
                    const optionsType = this.getType(options)
                    if (optionsType === 'function') {
                        item.options = options()
                    }

                    if (optionsType === 'asyncfunction') {
                        item.options = await options()
                    }
                }

                switch (type) {
                    case 'select':
                        if (clearable !== false) {
                            item.clearable = true
                        }
                        if (filterable !== false) {
                            item.filterable = true
                        }
                        break
                    case 'datetimerange':
                        if (this.isArray(modelName)) {
                            // 对于时间范围的情况，需要整合参数
                            const modelNameKey = modelName.join('&')
                            this.$set(item, modelNameKey, modelNameKey)
                            this.$set(item, 'isArray', true)
                            const defaultValue = []
                            modelName.forEach(itey=>{
                                defaultValue.push(this.formData[itey])
                            })
                            this.formData[modelNameKey] = defaultValue
                        }
                        break
                }
            }
        },
        getStype1() {
            return {
                'grid-template-columns': `repeat(${this.grid}, 1fr)`,
            }
        },
        getStyle({ grid }) {
            if (!this.grid || !grid) {
                return {}
            }
            // this.grid 表示一共有多少列  grid表示当前项，占几列
            if (grid === -1) {
                return { 'grid-column': `1 / -1` }
            }
            return { 'grid-column': `span ${grid}` }
        },
        // select类型下拉切换回调，添加自定义拦截功能，向下兼容
        async handleSelectChange(val, item) {
            if (item.beforeChange) {
                const res = await item.beforeChange(val, this.formData[item.modelName])
                if (res === false) return
            }
            this.$emit('handleChange', val, item)
            // this.$set(this.formData, item.modelName, val)
        },
        handleSelectRemote(query, item) {
            if (item.remoteMethod) {
                item.remoteMethod(query, item)
            }
        },
        handleSelectClear(item) {
            if (item.clear) {
                item.clear(item)
            }
        },
        handleSelectFocus(val, item) {
            if (item.beforeFocus) {
                item.beforeFocus(val, this.formData[item.modelName])
            }
        },
        async validateFn() {
            try {
                let a = await this.$refs.submitFormRef.validate()
                return a
            } catch (error) {
                return Promise.resolve(false)
            }
        },
        validateField(ids = [], cb) {
            this.$refs.submitFormRef.validateField(ids, (valid) => {
                if (typeof cb === 'function') {
                    cb(valid)
                }
                return valid
            })
        },
        clearValidate(ids = []) {
            this.$refs.submitFormRef.clearValidate(ids)
        },
        toggleForm() {
            this.formStatus = !this.formStatus
        },
        reset() {
            this.$emit('resetFieldFn')
            this.$refs.submitFormRef && this.$refs.submitFormRef.resetFields()
        },
        search() {
            const obj = {}
            for (const q in this.formData) {
                if (q.indexOf('&') !== -1) {
                    const arr = q.split('&')
                    arr.forEach((k, i) => {
                        obj[k] = this.formData[q] ? this.formData[q][i] : ''
                    })
                    delete obj[q]
                } else {
                    obj[q] = this.formData[q]
                }
            }
            this.$emit('search', obj)
        },
    },
}
</script>

<style lang="scss" scoped>
.selected-label {
    overflow: hidden;
    display: inline-block;
    margin-left: 0.5em;
    max-width: 200px;
    vertical-align: middle;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.sqForm {
    height: 40px !important;
    overflow: hidden;
}

.form-item-tips {
    font-size: 13px;
    color: red;
}
.select-option-width-auto {
    width: auto;
}
.select-option-width {
    overflow: hidden;
    display: inline-block;
    width: 200px;
    text-overflow: ellipsis;
}
.span-block {
    display: block;
}

::v-deep {
    .widthStyle {
        .el-input-number .el-input__inner {
            text-align: left;
        }
    }
}

.grid_list {
    display: grid;
    justify-content: space-between;
    grid-gap: 10px;
}
.grid_list_auto {
    grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
}
</style>
